package vfs.persist.association;

import vfs.except.VFSException;
import vfs.filter.VFSFilter;
import vfs.obj.entity.VFSEntity;
import java.util.Iterator;

/**
 * A VFSAssociationManager manages associations of different cardinalities
 * between different types of entities.
 * 
 * @author Matthew Eavenson <durandal@uga.edu>
 */
public interface VFSAssociationManager<T extends VFSEntity, U extends VFSEntity> {
    
    /*****************************************************************************
     * Find an object of type T referenced from an object of type U.
     * Works for 1-to-Many associations returning an object of type T on the one side.
     * @param uObj object of type U
     * @return an object of type T
     */
    T findT1M(U uObj) throws VFSException;

    /*****************************************************************************
     * Find an object of type U referenced from an object of type T.
     * Works for Many-to-1 associations returning an object of type U on the one side.
     * @param tObj object of type T
     * @return an object of type U
     */
    U findUM1(T tObj) throws VFSException;

    /*****************************************************************************
     * Find all objects of type T referenced from an object of type U, and filtered
     * by a given filter.
     * Works for Many-to-1 associations returning an object of type T on the many side.
     * @param uObj object of type U
     * @param filter a filter on the resulting set of T objects
     * @return an iterator of objects of type T
     */
    Iterator<T> findTM1(U uObj, VFSFilter filter) throws VFSException;

    /*****************************************************************************
     * Find all objects of type U referenced from an object of type T, and filtered
     * by a given filter.
     * Works for 1-to-Many associations returning an object of type U on the many side.
     * @param tObj object of type T
     * @param filter a filter on the resulting set of U objects
     * @return an iterator of objects of type U
     */
    Iterator<U> findU1M(T tObj, VFSFilter filter) throws VFSException;

    /*****************************************************************************
     * Find all objects of type T referenced from an object of type U, and filtered
     * by a given filter.
     * Works for Many-to-Many associations, returning objects of type T
     * @param uObj object of type U
     * @param filter a filter on the resulting set of T objects
     * @return an iterator of objects of type T
     */
    Iterator<T> findTMM(U uObj, VFSFilter filter) throws VFSException;

    /*****************************************************************************
     * Find all objects of type U referenced from an object of type T, and filtered
     * by a given filter.
     * Works for Many-to-Many associations, returning objects of type U
     * @param tObj object of type T
     * @param filter a filter on the resulting set of U objects
     * @return an iterator of objects of type U
     */
    Iterator<U> findUMM(T tObj, VFSFilter filter) throws VFSException;

    /*****************************************************************************
     * Store the association between an object of type T and an object of type U
     * to the storage medium.
     * For Many-to-1 associations.
     * @param entityT object of type T (many side)
     * @param entityU object of type U (one side)
     */
    void persistM1(T entityT, U entityU) throws VFSException;

    /*****************************************************************************
     * Store the association between an object of type T and an object of type U
     * to the storage medium.
     * For 1-to-Many associations.
     * @param entityT the object of type T (one side)
     * @param entityU the object of type U (many side)
     */
    void persist1M(T entityT, U entityU) throws VFSException;

    /*****************************************************************************
     * Store the association between an object of type T and an object of type U
     * to the storage medium.
     * For Many-to-Many associations.
     * @param entityT object of type T
     * @param entityU object of type U
     */
    void persistMM(T entityT, U entityU) throws VFSException;

    /*****************************************************************************
     * Remove an association from an object of type T by setting the
     * object's foreign key to null.
     * For Many-to-0 associations (i.e., one-side is optional).
     * @param entity object of type T
     */
    void removeM0(T entity) throws VFSException;

    /*****************************************************************************
     * Remove a Many-to-1 association from an object of type T.  This is not
     * supported since it would violate a NOT NULL constraint in the database.
     * For Many-to-1 associations (i.e., one-side is mandatory).
     * @param entityT an object of type T
     * @param entityU an object of type U
     */
    void removeM1(T entityT, U entityU) throws VFSException;

    /*****************************************************************************
     * Remove an association from an object of type U by setting the
     * object's foreign key to null.
     * For 0-to-Many associations (i.e., one-side is optional).
     * @param entity object of type U
     */
    void remove0M(U entity) throws VFSException;

    /*****************************************************************************
     * Remove a 1-to-Many association from an object of type U.  This is not
     * supported since it would violate a NOT NULL constraint in the database.
     * For 1-to-Many associations (i.e., one-side is mandatory).
     * @param entityT an object of type T
     * @param entityU an object of type U
     */
    void remove1M(T entityT, U entityU) throws VFSException;

    /*****************************************************************************
     * Remove a Many-to-Many association between two entities.
     * For Many-to-Many associations.
     * @param entityT an object of type T
     * @param entityU an object of type U
     */
    void removeMM(T entityT, U entityU) throws VFSException;

    
}
